# Copyright (c) 2025 Songwufeng
# [Software Name] is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import os
import ctypes
import pyautogui
import time
from math import sqrt
from screenshot import get_target_center_coordinates
from pynput import keyboard
import tkinter as tk
from tkinter import ttk


class PID:
    def __init__(self, P=2.0, I=0.02, D=0.5):  # 增大 P 值以加快响应速度
        self.kp, self.ki, self.kd = P, I, D
        self.uPrevious, self.uCurent = 0, 0
        self.setValue, self.lastErr, self.errSum = 0, 0, 0
        self.errSumLimit = 10

    def pidPosition(self, setValue, curValue):
        err = setValue - curValue
        dErr = err - self.lastErr
        self.errSum += err
        outPID = self.kp * err + self.ki * self.errSum + self.kd * dErr
        self.lastErr = err
        return outPID


class LOGITECH:
    def __init__(self):
        self.dll = None
        self.state = False
        self.load_dll()

    def load_dll(self):
        try:
            file_path = os.path.abspath(os.path.dirname(__file__))
            self.dll = ctypes.CDLL(f'{file_path}/logitech.driver.dll')
            self.dll.device_open.restype = ctypes.c_int
            result = self.dll.device_open()
            self.state = (result == 1)
            self.dll.moveR.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_bool]
            self.dll.moveR.restype = None
        except FileNotFoundError:
            print(f'错误, 找不到 DLL 文件')
        except OSError as e:
            print(f'错误, 加载 DLL 文件失败: {e}')

    def mouse_move(self, end_xy, min_xy=0.5, distance_threshold=5, max_x_move=500, max_y_move=400):
        if not self.state:
            return

        end_x, end_y = end_xy
        new_x, new_y = pyautogui.position()

        # 计算目标坐标与当前鼠标坐标的距离
        distance = sqrt((end_x - new_x) ** 2 + (end_y - new_y) ** 2)
        print(f"目标坐标与当前鼠标坐标的距离: {distance}")

        # 如果距离小于阈值，不进行移动
        if distance < distance_threshold:
            print("距离小于阈值，不进行移动")
            return

        pid_x = PID(P=sensitivity)
        pid_y = PID(P=sensitivity)

        move_x = pid_x.pidPosition(end_x, new_x)
        move_y = pid_y.pidPosition(end_y, new_y)

        # 限制 x 轴移动范围
        move_x = max(-max_x_move, min(max_x_move, move_x))
        # 限制 y 轴移动范围
        move_y = max(-max_y_move, min(max_y_move, move_y))

        move_x = max(min_xy, move_x) if move_x > 0 else min(-min_xy, move_x) if move_x < 0 else int(move_x)
        move_y = max(min_xy, move_y) if move_y > 0 else min(-min_xy, move_y) if move_y < 0 else int(move_y)

        move_x = int(move_x)
        move_y = int(move_y)

        print(f"传递给 moveR 的参数: x={move_x}, y={move_y}")
        result = self.dll.moveR(move_x, move_y, True)
        print(f"moveR 函数的返回值: {result}")


logitech = LOGITECH()
aiming = False  # 新增状态变量，用于跟踪是否正在瞄准
sensitivity = 2.0  # 初始化灵敏度


def move_mouse_to_coordinate(end_xy):
    logitech.mouse_move(end_xy)


def on_press(key):
    global aiming
    try:
        if key == keyboard.Key.shift:
            aiming = True  # 按下 Shift 键，开始瞄准
    except AttributeError:
        pass


def on_release(key):
    global aiming
    if key == keyboard.Key.shift:
        aiming = False  # 松开 Shift 键，停止瞄准
    if key == keyboard.Key.esc:
        return False


def update_sensitivity(value):
    global sensitivity
    sensitivity = float(value)
    print(f"当前灵敏度: {sensitivity}")


# 创建 Tkinter 窗口
root = tk.Tk()
root.title("灵敏度调整")

# 创建滑动条
sensitivity_scale = ttk.Scale(root, from_=0.1, to=5.0, orient=tk.HORIZONTAL,
                              command=update_sensitivity, value=sensitivity)
sensitivity_scale.pack(pady=20)

# 启动 Tkinter 窗口的事件循环
root.update()
root.withdraw()  # 隐藏窗口，避免干扰


with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
    try:
        while True:
            if aiming:
                # 获取目标中心坐标
                coordinates = get_target_center_coordinates()
                if coordinates:
                    print(coordinates)
                    # 假设 coordinates 是一个包含 (x, y) 坐标的元组或列表
                    move_mouse_to_coordinate(coordinates)
            time.sleep(0.05)  # 缩短循环时间间隔
            root.update()  # 更新 Tkinter 窗口
    except KeyboardInterrupt:
        print("程序已被手动中断，正在退出...")
        root.destroy()  # 关闭 Tkinter 窗口